package com.atguigu.yygh.cmn.service.impl;


import cn.hutool.core.util.StrUtil;
import com.alibaba.excel.EasyExcel;
import com.atguigu.yygh.cmn.listener.DictListener;
import com.atguigu.yygh.cmn.mapper.DictMapper;
import com.atguigu.yygh.cmn.service.DictService;
import com.atguigu.yygh.model.cmn.Dict;
import com.atguigu.yygh.vo.cmn.DictEeVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 组织架构表 服务实现类
 * </p>
 *
 * @author 孔德成
 * @since 2021-08-31
 */
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {

    private final DictListener dictListener;

    public DictServiceImpl(DictListener dictListener) {
        this.dictListener = dictListener;
    }

    /**
     * value = "dict", key = "'selectIndexList'+#id"
     * redis 中的key - dict::selectIndexList110000
     */
    @Cacheable(value = "dict", key = "'selectIndexList'+#id")
    @Override
    public List<Dict> findChildData(Long id) {
        // 返回子节点列表，并判断每个子节点是否还有子节点，封装属性 hasChildren
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", id);
        List<Dict> dicts = baseMapper.selectList(wrapper);
        for (int i = 0; i < dicts.size(); i++) {
            Dict dict = dicts.get(i);
            dict.setHasChildren(hasChildren(dict));
        }
        return dicts;
    }

    @Override
    public void exportData(HttpServletResponse response) {
        try {
            // 设置响应类型
            response.setContentType("application/vnd.ms-excel");
            // 设置响应编码格式
            response.setCharacterEncoding("utf-8");
            // 对中文文件名进行编码
            String fileName = URLEncoder.encode("数据字典", "UTF-8");
            // 告诉浏览器以附件形式打开该文件
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

            // 查询数据库，获取所有数据字典数据
            List<Dict> data = baseMapper.selectList(null);
            // 将数据封装到 excel 实体中
            ArrayList<DictEeVo> dictEeVos = new ArrayList<>(data.size());
            for (Dict datum : data) {
                DictEeVo dictEeVo = new DictEeVo();
                BeanUtils.copyProperties(datum, dictEeVo);
                dictEeVos.add(dictEeVo);
            }
            // 写入 excel
            EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("数据字典").doWrite(dictEeVos);

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    @Override
    public void importDictData(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(), DictEeVo.class, dictListener).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * # 初始化医院信息中的数据字典数据（医院等级，省，市，区...）
     * # 直接根据值查询，可能查询出重复数据
     * SELECT * from dict where value = 1
     * # 如何查询？以查询医院等级为例
     * # 1. 使用辅助字段 dict_code=Hostype 查询医院等级的 id
     * select * from dict where dict_code="Hostype"
     * # 根据医院等级的 id 查询出所有的医院等级(缩小 value 的查询范围)
     * # select * from dict where parent_id in (select id from dict where dict_code="Hostype")
     * # 使用 id 和 值查询即可
     * select * from dict where parent_id = 10000 and value = 1
     *
     * @param dictCode 辅助字段
     * @param value    值
     * @return
     */
    @Override
    public String getNameByDictCodeAndValue(String dictCode, String value) {
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        if (StrUtil.isNotBlank(dictCode)) {
            wrapper.eq("dict_code", dictCode);
            Dict dictTemp = baseMapper.selectOne(wrapper);
            QueryWrapper<Dict> wrapper1 = new QueryWrapper<>();
            Map<String, Object> map = new HashMap<>(2);
            map.put("parent_id", dictTemp.getId());
            map.put("value", value);
            wrapper1.allEq(map);
            return baseMapper.selectOne(wrapper1).getName();
        } else {
            wrapper.eq("value", value);
            return baseMapper.selectOne(wrapper).getName();
        }
    }

    @Override
    public List<Dict> findByDictCode(String dictCode) {
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("dict_code", dictCode);
        // 根据 dictCode 查询 id
        Dict dict = baseMapper.selectOne(wrapper);
        // 根据 parent_id 查询数据列表
        Long id = dict.getId();
        return baseMapper.selectList(new QueryWrapper<Dict>().eq("parent_id", id));
    }

    /**
     * 判断某个节点是否还有子节点
     *
     * @param dict
     * @return
     */
    private boolean hasChildren(Dict dict) {
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", dict.getId());
        return baseMapper.selectCount(wrapper) > 0;
    }
}
